from PIL import Image
from PyQt5 import QtGui , sip
from PyQt5.QtCore import QSize, pyqtSignal, Qt, QThread
from PyQt5.QtGui import QPainter, QFont, QColor, QPixmap, QPolygon, QFontMetrics
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QVBoxLayout, QSpacerItem, \
    QScrollArea, QScrollBar , QTextBrowser , QPushButton



class MessageType:
    Text = 1
    Image = 2


class TextMessage(QLabel):
    heightSingal = pyqtSignal(int)

    def __init__(self, text, is_send=False, parent=None):
        super(TextMessage, self).__init__(text, parent)
        self.font = QFont('微软雅黑', 12)
        self.setFont(self.font)
        self.setWordWrap(True)
        self.setMaximumWidth(1600)
        self.setMinimumWidth(100)
        self.setMinimumHeight(45)
        self.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        if is_send:
            self.setAlignment(Qt.AlignCenter | Qt.AlignRight)
            self.setStyleSheet(
                '''
                background-color:#39c5bb;
                border-radius:10px;
                padding:10px;
                '''
            )
        else:
            self.setAlignment(Qt.AlignLeft | Qt.AlignCenter)
            self.setStyleSheet(
                '''
                background-color:#66ccff;
                border-radius:10px;
                padding:10px;
                '''
            )
        
        font_metrics = QFontMetrics(self.font)
        rect = font_metrics.boundingRect(text)
        self.setMaximumWidth(rect.width()+60)

    def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
        super(TextMessage, self).paintEvent(a0)

    def append(self,appendText) -> None:
        if(self.text() == '思考中，请稍候。。。'):
            self.clear()
        self.setMaximumWidth(self.width()+30)
        self.setText(self.text() + str(appendText))
        self.setAlignment(Qt.AlignLeft)
        # self.append(str(appendText))

class Triangle(QLabel):
    def __init__(self, Type, is_send=False, parent=None):
        super().__init__(parent)
        self.Type = Type
        self.is_send = is_send
        self.setFixedSize(6, 45)

    def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
        super(Triangle, self).paintEvent(a0)
        if self.Type == MessageType.Text:
            painter = QPainter(self)
            triangle = QPolygon()
            if self.is_send:
                painter.setPen(QColor('#39c5bb'))
                painter.setBrush(QColor('#39c5bb'))
                triangle.setPoints(0, 20, 0, 34, 6, 27)
            else:
                painter.setPen(QColor('#66ccff'))
                painter.setBrush(QColor('#66ccff'))
                triangle.setPoints(0, 27, 6, 20, 6, 34)
            painter.drawPolygon(triangle)


class Notice(QLabel):
    def __init__(self, text, type_=3, parent=None):
        super().__init__(text, parent)
        self.type_ = type_
        self.setFont(QFont('微软雅黑', 12))
        self.setWordWrap(True)
        self.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.setAlignment(Qt.AlignCenter)


class Avatar(QLabel):
    def __init__(self, avatar, parent=None):
        super().__init__(parent)
        if isinstance(avatar, str):
            self.setPixmap(QPixmap(avatar).scaled(45, 45))
            self.image_path = avatar
        elif isinstance(avatar, QPixmap):
            self.setPixmap(avatar.scaled(45, 45))
        self.setFixedSize(QSize(45, 45))


class OpenImageThread(QThread):                     # 打开图像的线程
    def __init__(self, image_path):
        super().__init__()
        self.image_path = image_path

    def run(self) -> None:
        image = Image.open(self.image_path)
        image.show()


class ImageMessage(QLabel):
    def __init__(self, avatar, parent=None):
        super().__init__(parent)
        self.image = QLabel(self)
        if isinstance(avatar, str):
            self.setPixmap(QPixmap(avatar))
            self.image_path = avatar
        elif isinstance(avatar, QPixmap):
            self.setPixmap(avatar)
        self.setMaximumWidth(480)
        self.setMaximumHeight(720)
        self.setScaledContents(True)

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:  # 左键按下
            self.open_image_thread = OpenImageThread(self.image_path)
            self.open_image_thread.start()


class BubbleMessage(QWidget):
    def __init__(self, str_content, avatar, Type, is_send=False, parent=None):
        super().__init__(parent)
        self.isSend = is_send
        # self.set
        self.setStyleSheet(
            '''
            border:none;
            '''
        )
        layout = QHBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 5, 5, 5)
        # self.resize(QSize(200, 50))
        self.avatar = Avatar(avatar)
        triangle = Triangle(Type, is_send)
        if Type == MessageType.Text:
            self.message = TextMessage(str_content, is_send)
            # self.message.setMaximumWidth(int(self.width() * 0.6))
        elif Type == MessageType.Image:
            self.message = ImageMessage(str_content)
        else:
            raise ValueError("未知的消息类型")

        self.spacerItem = QSpacerItem(45 + 6, 45, QSizePolicy.Expanding, QSizePolicy.Minimum)
        if is_send == False:
            layout.addItem(self.spacerItem)
            layout.addWidget(self.message, 1)
            layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignLeft)
            layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignLeft)
        else:
            layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignRight)
            layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignRight)
            layout.addWidget(self.message, 1)
            layout.addItem(self.spacerItem)
        self.setLayout(layout)

    def MessageAppend(self,text) -> None:
        self.message.append(text)


class ScrollAreaContent(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.adjustSize()


class ScrollArea(QScrollArea):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWidgetResizable(True)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setStyleSheet(
            '''
            border:none;
            '''
        )


class ScrollBar(QScrollBar):
    def __init__(self):
        super().__init__()
        self.setStyleSheet(
            '''
          QScrollBar:vertical {
              border-width: 0px;
              border: none;
              background:rgba(64, 65, 79, 0);
              width:5px;
              margin: 0px 0px 0px 0px;
          }
          QScrollBar::handle:vertical {
              background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
              stop: 0 #DDDDDD, stop: 0.5 #DDDDDD, stop:1 #aaaaff);
              min-height: 20px;
              max-height: 20px;
              margin: 0 0px 0 0px;
              border-radius: 2px;
          }
          QScrollBar::add-line:vertical {
              background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
              stop: 0 rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0),  stop:1 rgba(64, 65, 79, 0));
              height: 0px;
              border: none;
              subcontrol-position: bottom;
              subcontrol-origin: margin;
          }
          QScrollBar::sub-line:vertical {
              background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
              stop: 0  rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0),  stop:1 rgba(64, 65, 79, 0));
              height: 0 px;
              border: none;
              subcontrol-position: top;
              subcontrol-origin: margin;
          }
          QScrollBar::sub-page:vertical {
              background: rgba(64, 65, 79, 0);
          }

          QScrollBar::add-page:vertical {
              background: rgba(64, 65, 79, 0);
          }
            '''
        )


class ChatWidget(QWidget):
    def __init__(self,parent = None):
        super().__init__()
        
        print(parent)
        self.resize(500, 200)

        layout = QVBoxLayout()          # 整个ChatWidget的layout
        layout.setSpacing(0)
        self.LayoutItemCount = 0
        self.adjustSize()

        self.bubbleList = []
        self.send_avatar = ''
        self.receive_avatar = ''

        # 生成滚动区域
        self.scrollArea = ScrollArea(self)
        scrollBar = ScrollBar()
        self.scrollArea.setVerticalScrollBar(scrollBar)
        # self.scrollArea.setGeometry(QRect(9, 9, 261, 211))
        # 生成滚动区域的内容部署层部件
        self.scrollAreaWidgetContents = ScrollAreaContent(self.scrollArea)
        self.scrollAreaWidgetContents.setMinimumSize(50, 100)
        # 设置滚动区域的内容部署部件为前面生成的内容部署层部件
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        layout.addWidget(self.scrollArea)
        self.layout0 = QVBoxLayout()                        # Layout0是容纳聊天气泡的Layout
        self.layout0.setSpacing(0)
        self.layout0.setAlignment(Qt.AlignTop)
        self.scrollAreaWidgetContents.setLayout(self.layout0)
        self.setLayout(layout)

    def add_message_item(self, bubble_message, index = -1):
        if index == -1:
            self.bubbleList.append(bubble_message)
            self.layout0.addWidget(self.bubbleList[-1])
            self.LayoutItemCount = self.layout0.indexOf(bubble_message)
            return self.LayoutItemCount
        else:
            self.bubbleList.insert(index,bubble_message)
            self.layout0.insertWidget(index, bubble_message)
        # self.set_scroll_bar_last()

    def set_scroll_bar_last(self):
        self.scrollArea.verticalScrollBar().setValue(
            self.scrollArea.verticalScrollBar().maximum()
        )

    def set_scroll_bar_value(self, val):
        self.verticalScrollBar().setValue(val)

    def verticalScrollBar(self):
        return self.scrollArea.verticalScrollBar()

    def appendPlainText(self,text,is_send = False):  # 添加新的聊天气泡
        if is_send:
            bubble_message = BubbleMessage(text, self.send_avatar,Type=MessageType.Text , \
                                       is_send=is_send)
        else:
            bubble_message = BubbleMessage(text, self.receive_avatar,Type=MessageType.Text , \
                                       is_send=is_send)
        self.add_message_item(bubble_message)
    
    def insertPlainText(self,text,index = 0,is_send = False):   # 在指定的位置添加聊天气泡
        if is_send:
            bubble_message = BubbleMessage(text, self.send_avatar,Type=MessageType.Text , \
                                       is_send=is_send)
        else:
            bubble_message = BubbleMessage(text, self.receive_avatar,Type=MessageType.Text , \
                                       is_send=is_send)
        self.add_message_item(bubble_message)

    def insertBubbleText(self,chunk:str,index:int = -1):     # 在指定的的一个聊天气泡里添加新的文本
        try:
            self.bubbleList[index].MessageAppend(chunk)
            self.bubbleList[index].repaint()
        # print(self.bubbleList[-1].message.text())
        # print(self.LayoutItemCount)
        except Exception:
            print('添加新文本失败')

    def setBubbleText(self,Text:str,index:int = -1):         # 设置聊天气泡的文本内容
        self.bubbleList[index].message.setText(Text)

    def chear(self):                                 # 清空聊天框
        for bubble in self.bubbleList:
            self.layout0.removeWidget(bubble)
            sip.delete(bubble)

        self.bubbleList = []

    def flush(self,flushList:list) -> None:          # 刷新聊天框
        self.chear()
        for item in flushList:
            if(item['role'] == "user"):
                self.appendPlainText(item['content'],is_send = True)
                self.bubbleList
            elif(item['role'] == "assistant"):
                self.appendPlainText(item['content'])
            else:
                self.add_message_item(Notice(item['content']))
                

    def update(self) -> None:
        super().update()
        self.scrollAreaWidgetContents.adjustSize()
        self.scrollArea.update()
        # self.scrollArea.repaint()
        # self.verticalScrollBar().setMaximum(self.scrollAreaWidgetContents.height())

    def setAvatar(self,send = '',receive = '') -> None:
        self.send_avatar = send
        self.receive_avatar = receive
